<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  这个文件是 JCAT PHP框架的一部，该项目和此文件 均遵循 GNU 自由软件协议
// 
//  Copyleft 2008 JeCat.cn(http://team.JeCat.cn)
//
//
//  JCAT PHP框架 的正式全名是：Jellicle Cat PHP Framework。
//  “Jellicle Cat”出自 Andrew Lloyd Webber的音乐剧《猫》（《Prologue:Jellicle Songs for Jellicle Cats》）。
//  JCAT 是一个开源项目，它像音乐剧中的猫一样自由，你可以毫无顾忌地使用JCAT PHP框架。
//  JCAT 由中国团队开发维护，是一个国际性的项目。
//  正在使用的这个版本是：0.3.2 / SVN信息：$Id: class.JCAT_Gtk.php 1250 2009-02-07 04:53:17Z aleechou $
//
//
//
//  相关的链接：
//    [主页] http://jcat.JeCat.cn
//    [HTTP下载] http://jcat.JeCat.cn/download
//    [在线文档] http://jcat.JeCat.cn/document
//    [社区] http://jj.jecat.cn/forum-7-1.html
//  不很相关：
//    [MP3] http://www.google.cn/search?q=jellicle+songs+for+jellicle+cats+Andrew+Lloyd+Webber
//    [VCD/DVD] http://www.google.cn/search?q=CAT+Andrew+Lloyd+Webber+video
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
/*-- Project Introduce --*/


class JCAT_Gtk
{
	/**
	 * 显示一个 消息对话框
	 *
	 * @access	public
	 * @param	$sLabel																		string					消息（正文）
	 * @param	$sMessageTitle																string					消息标题
	 * @param	$nDlgType=Gtk::MESSAGE_INFO												int:GtkMessageType		对话框 类型
	 * @param	$nButtonFlags=Gtk::BUTTONS_OK											int:GtkButtonsType		按钮
	 * @param	$nDlgFlags=Gtk::DIALOG_MODAL|Gtk::DIALOG_DESTROY_WITH_PARENT		int:GtkDialogFlags		对话框 特性
	 * @param	$aParentWidget=null															GtkWidget				父窗口
	 * @return	int
	 */
	static public function MessageDialog( $sLabel, $sMessageTitle='', $nDlgType=Gtk::MESSAGE_INFO, $nButtonFlags=Gtk::BUTTONS_OK, $nDlgFlags=3, GtkWidget $aParentWidget=null )
	{
		$aDialog = new GtkMessageDialog($aParentWidget, $nDlgFlags, $nDlgType, $nButtonFlags, $sMessageTitle );
		
		if( !empty($sLabel) )
		{
			$aDialog->set_markup($sLabel);
		}
		if( empty($sMessageTitle) )
		{
			$sMessageTitle = JCAT_Language::SentenceEx('JCAT PHP Desktop Message Dialog','JCAT',null) ;
		}

		$aDialog->set_title($sMessageTitle) ;
		$aDialog->set_position(Gtk::WIN_POS_CENTER) ;
		$nRet = $aDialog->run() ;

		$aDialog->destroy() ;
		
		return $nRet ;
	}
	
	/**
	 * 此函数是 JCAT_Gtk::MessageDialog() 的别名
	 *
	 * @access	public
	 * @param	$sLabel																		string					消息（正文）
	 * @param	$sMessageTitle																string					消息标题
	 * @param	$nDlgType=Gtk::MESSAGE_INFO												int:GtkMessageType		对话框 类型
	 * @param	$nButtonFlags=Gtk::BUTTONS_OK											int:GtkButtonsType		按钮
	 * @param	$nDlgFlags=Gtk::DIALOG_MODAL|Gtk::DIALOG_DESTROY_WITH_PARENT		int:GtkDialogFlags		对话框 特性
	 * @param	$aParentWidget=null															GtkWidget				父窗口
	 * @return	int
	 */
	static public function MsgDlg( $sLabel, $sMessageTitle='', $nDlgType=Gtk::MESSAGE_INFO, $nButtonFlags=Gtk::BUTTONS_OK, $nDlgFlags=3, GtkWidget $aParentWidget=null )
	{
		$arrArgvs =& func_get_args() ;
		return call_user_func_array( array(__CLASS__,'MessageDialog'), &$arrArgvs ) ;
	}

	
	/**
	 * 显示一个 确认对话框
	 *
	 * @access	public
	 * @param	$sLabel																		string					消息（正文）
	 * @param	$sMessageTitle																string					消息标题
	 * @param	$nDlgFlags=Gtk::DIALOG_MODAL|Gtk::DIALOG_DESTROY_WITH_PARENT		int:GtkDialogFlags		对话框 特性
	 * @param	$aParentWidget=null															GtkWidget				父窗口
	 * @static
	 * @return	bool
	 */
	static public function ConfirmDialog( $sLabel, $sMessageTitle='', $nDlgFlags=3, GtkWidget $aParentWidget=null )
	{		
		return (self::MessageDialog($sLabel,$sMessageTitle,Gtk::MESSAGE_QUESTION,Gtk::BUTTONS_YES_NO,$nDlgFlags,$aParentWidget)===Gtk::RESPONSE_YES) ;
	}
	
	/**
	 * 寻找Gtk样式
	 *
	 * @access	public
	 * @return	array
	 */
	static public function FindStyle( $sStylesDir, array $arrGtkrcFilenamePattern=array('/^gtkrc$/i') )
	{
		JCAT_ASSERT::ASSERT_DIR($sStylesDir) ;
		JCAT_ASSERT::ASSERT_ISTHESE($arrGtkrcFilenamePattern,array('array:string')) ;
		
		$arrRet = array() ;
		$nUnnameStyleIdx = 1 ;
		
		$aIterator = new JCAT_FSOTreeIterator( $sStylesDir, JCAT_FSOIterator::FILE|JCAT_FSOIterator::RETURN_FSO ) ;
		while( !$aIterator->IsDone() )
		{
			$aFile = $aIterator->Current() ;
			
			foreach($arrGtkrcFilenamePattern as $sPattern)
			{
				if( preg_match($sPattern,$aFile->GetName()) )
				{
					$sStyleNameFile = $aFile->GetParentDirectory().'StyleName.txt' ;
					if( is_file($sStyleNameFile) )
					{
						$sStyleName = file_get_contents($sStyleNameFile) ;
					}
					else
					{
						$sStyleName = JCAT_Language::SentenceEx('未命名样式 %d','JCAT',null,$nUnnameStyleIdx++) ;
					}
					
					$arrRet[$sStyleName] = $aFile->GetPath() ;
					break ;
				}
			}
			
			$aIterator->Next() ;
		}
		
		
		return $arrRet ;
	}
	
	
	/**
	 * 在浏览器中打开网页
	 *
	 * @access	public
	 * @param	$sUrl
	 * @static
	 * @return	void
	 */
	static public function OpenUrlInBrowser($sUrl)
	{
		// Windows 平台
		if( isset($_ENV['OS']) and preg_match('/^windows/i',$_ENV['OS']) )
		{
			exec("start {$sUrl}") ;
		}
		
		// 尝试使用 Gnome 环境 中的命名
		else
		{
			exec("gnome-open {$sUrl}") ;
		}
	}
	
	/**
	 * 开始后台工作， 允许 PHP 在执行一项长时间工作的同时，Gtk用户界面 仍然能够响应用户的输入
	 *
	 * @access	public
	 * @param	$nSensitivity=1	int		在工作期间，Gtk用户界面 的响应灵敏度， 数值越小，灵敏度越高。该数值不能小于1
	 * @return	void
	 */
	static public function StartBackgroundWork( $nSensitivity=1 )
	{
		JCAT_ASSERT::ASSERT_($nSensitivity>=1,JCAT_Language::SentenceEx('参数 $nSensitivity 不能小于1','JCAT',null)) ;
		
		register_tick_function( array(__CLASS__,'CheckSignal') ) ;
		declare(ticks=1) ;
	}
	
	/**
	 * 结束后台工作
	 *
	 * @access	public
	 * @return	void
	 */
	static public function EndBackgroundWork()
	{
		unregister_tick_function( array(__CLASS__,'CheckSignal') ) ;
	}
	
	
	/**
	 * 堵塞等待消息
	 *
	 * @access	public
	 * @return	void
	 */
	static public function Block()
	{
		self::$bBlocking = true ;
		
		// Gtk 处理回调函数
		register_tick_function( array(__CLASS__,'CheckSignal') ) ;
		declare(ticks=1) ;
		
		// 检查状态
		while( self::$bBlocking )
		{
			// 后台任务
			if( self::$arrBackgroupWorkCallback )
			{
				$arrCallback = self::$arrBackgroupWorkCallback ;
				self::$arrBackgroupWorkCallback = null ;
				
				call_user_func_array($arrCallback,self::$arrBackgroupWorkArgvs) ;
			}
			
		}
		
		// 取消回调函数
		unregister_tick_function( array(__CLASS__,'CheckSignal') ) ;
	}
	
	/**
	 * 退出堵塞
	 *
	 * @access	public
	 * @return	void
	 */
	public function QuitBlock()
	{
		self::$bBlocking = false ;
	}
	
	
	/**
	 * 检查Gtk信号
	 *
	 * @access	public
	 * @return	void
	 */
	static function CheckSignal()
	{
		// Gtk 视窗信号
		if(Gtk::events_pending())
		{
			Gtk::main_iteration() ;
		}
	}
	
	
	/**
	 * 在堵塞状态时，执行一个后台函数。
	 *
	 * @access	public
	 * @param	$Callback		What's this Parameter ?
	 * @param	$arrArgvs		What's this Parameter ?
	 * @return	void
	 */
	public function RunBackgroupWork( $Callback, array $arrArgvs=array() )
	{
		JCAT_ASSERT::ASSERT_(is_callable($Callback),JCAT_Language::SentenceEx('参数必须是有效的 回调函数','JCAT',null)) ;
		
		self::$arrBackgroupWorkCallback = $Callback ;
		self::$arrBackgroupWorkArgvs = $arrArgvs ;
	}
	
	
	
	// 后台任务 回调函数
	static private $arrBackgroupWorkCallback ;
	static private $arrBackgroupWorkArgvs ;
	
	// Block 状态
	static private $bBlocking = false ;
	
	
	
	/**
	 * what's this
	 * 
	 * @access	public
	 * @param	$aItem						GtkTreeIter 	源变量
	 * @param	$MappingData				mixed			映射变量
	 * @param	$sMappingName='unknow'		string			映射名称
	 * @static 
	 * @return	old_value
	 */
	static public function MapGtkItemToData(GtkTreeModel $aModel,GtkTreeIter $aItem,$MappingData,$sMappingName='unknow')
	{
		JCAT_ASSERT::ASSERT_STRING($sMappingName) ;
		$sRealMappingName = $aModel->get_string_from_iter($aItem).'>'.$sMappingName ; 
		
		if( self::$aMapItemToData===null )
		{
			self::$aMapItemToData = new JCAT_Map() ;
		}
		
		return self::$aMapItemToData->Set($aModel,$MappingData,$sRealMappingName) ;		
	}
	
	
	/**
	 * what's this
	 * 
	 * @access	public
	 * @param	$aModel						GtkTreeModel 	模型
	 * @param	$aItem							GtkTreeIter 	源变量
	 * @param	$sMappingName='unknow'		string			映射名称
	 * @static
	 * @return	mixed
	 */
	static public function GetGtkItemData(GtkTreeModel $aModel,GtkTreeIter $aItem,$sMappingName='unknow')
	{
		if( self::$aMapItemToData===null )
		{
			return null ;
		}
			
		JCAT_ASSERT::ASSERT_STRING($sMappingName) ;
		$sRealMappingName = $aModel->get_string_from_iter($aItem).'>'.$sMappingName ; 
		
		return self::$aMapItemToData->Get($aModel,$sRealMappingName) ;		
	}

	/**
	 * 检查 PHP-Gtk 版本是否为 2.0 以上
	 *
	 * @access	public
	 * @static
	 * @return	bool
	 */
	static public function IsPHPGtk2()
	{
		return defined("GObject::TYPE_STRING") ;
	}
	
	/**
	 * 取得 Gtk 版本
	 *
	 * @access	public
	 * @static
	 * @return	JCAT_Version
	 */
	static public function GetGtkVersion()
	{
		$sVersion = Gtk::get_version() ;
		$sVersion = str_replace('Gtk','',$sVersion) ;
		$sVersion = trim($sVersion) ;
		
		list($nPriVer,$nSecVer,$nThdVer) = explode('.',$sVersion) ;
		$aVersion = new JCAT_Version($nPriVer,$nSecVer,$nThdVer) ;
		return $aVersion ;
	}
		
	static private $aMapItemToData ;
	
	
}



?>